/*
  Author: Chen Haodong (shinkunyachen@outlook.com)
  -----
  Copyright (c)2020 - present Chen Haodong. All Rights Reserved.
 */

#ifndef DETECT_ME_H
#define DETECT_ME_H

#include "framework/BasicChecker.h"
#include "DetectMe/Report.h"
// TODO detect loop
// traverse back to find whether a block has terminator which is loop
// need cache
class DetectMe : public BasicChecker {
public:
  enum Color {
    White,
    Black,
  };

public:
  struct WalkContext {
    //
    WalkContext(clang::CFG *c) : cfg(c) {}
    //
    clang::CFG *cfg;
    const clang::CFGBlock *block;
    clang::CFGBlock::const_reverse_iterator stmt_it;
    ASTFunction *function;
  };

public:
  DetectMe(ASTResource *resource, ASTManager *manager, CallGraph *call_graph,
           Config *configure)
      : BasicChecker(resource, manager, call_graph, configure) {}

  void check();

private:
  void walk(const clang::CFGBlock *blk, WalkContext &ctx);
  void walk(const clang::Stmt *stmt, WalkContext &ctx);
  void walk(const clang::Expr *expr, WalkContext &ctx);
  void walk(const clang::BinaryOperator *expr, WalkContext &ctx);

  void reportJson(const clang::Expr *,WalkContext &ctx,DefectType dt);

  void detect_pointer_arithmetic_oob(const clang::BinaryOperator *expr,
                                     WalkContext &ctx);
  void detect_array_oob_in_loop(const clang::ArraySubscriptExpr *expr,
                                WalkContext &ctx);
  void detect_cast_oob(const clang::MemberExpr *expr, WalkContext &ctx);
  //void detect_dereference_oob_after_arithmetic_overflow()// unknown
  void detect_infinite_loop(const clang::Expr *expr, WalkContext &ctx); // unknown
  void detect_divmod_zero(const clang::BinaryOperator *expr,
                                     WalkContext &ctx);
  // void detect_sql_inject(); // unknown
  bool detect_arithmetic_overflow(const clang::Expr *expr, WalkContext &ctx);
  void detect_null_dereference(const clang::UnaryOperator *expr,
                               WalkContext &ctx);
  void detect_use_after_free(const clang::UnaryOperator *expr,
                             WalkContext &ctx);
  //void detect_illegal_element_access(); // unknown
  //void detect_illegal_file_path(); // unknown
};
#endif